﻿/******************************************************************************
 * 
 * Announce: CSharpKit, Basic algorithms, components and definitions.
 *           Copyright (C) ShenYongchen.
 *           All rights reserved.
 *   Author: 申永辰.郑州 (shenyczz@163.com)
 *  WebSite: http://github.com/shenyczz/CSharpKit
 *
 * THIS CODE IS LICENSED UNDER THE MIT LICENSE (MIT).
 * THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF 
 * ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
 * IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
 * PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
 * 
******************************************************************************/

using System;
using CSharpKit.Numerics.LinearAlgebra.Factorization;

namespace CSharpKit.Numerics.LinearAlgebra
{
    // Matrix.Solve（矩阵求解）
    //
    // Factorizations               - 因式分解
    // Direct Solvers: Full         - 直接求解器
    // Direct Solvers: Simple       - 直接求解器
    // Iterative Solvers: Full      - 迭代求解
    // Iterative Solvers: Simple    - 迭代求解
    partial class Matrix<T>
    {
        // Direct Solvers: Full - 直接求解器

        /// <summary>
        /// Solves a system of linear equations, <b>AX = B</b>, with A QR factorized.
        /// </summary>
        /// <param name="input">The right hand side <see cref="Matrix{T}"/>, <b>B</b>.</param>
        /// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>X</b>.</param>
        public void Solve(Matrix<T> input, Matrix<T> result)
        {
            if (ColumnCount == RowCount)
            {
                LU().Solve(input, result);
                return;
            }

            QR().Solve(input, result);
        }

        /// <summary>
        /// Solves a system of linear equations, <b>Ax = b</b>, with A QR factorized.
        /// </summary>
        /// <param name="input">The right hand side vector, <b>b</b>.</param>
        /// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>x</b>.</param>
        public void Solve(Vector<T> input, Vector<T> result)
        {
            if (ColumnCount == RowCount)
            {
                // 行列相等使用LU分解
                LU().Solve(input, result);
                return;
            }

            QR().Solve(input, result);
        }



        // Direct Solvers: Simple

        /// <summary>
        /// Solves a system of linear equations, <b>AX = B</b>, with A QR factorized.
        /// </summary>
        /// <param name="input">The right hand side <see cref="Matrix{T}"/>, <b>B</b>.</param>
        /// <returns>The left hand side <see cref="Matrix{T}"/>, <b>X</b>.</returns>
        public Matrix<T> Solve(Matrix<T> input)
        {
            var x = Builder.SameAs(this, ColumnCount, input.ColumnCount, fullyMutable: true);
            Solve(input, x);
            return x;
        }

        /// <summary>
        /// Solves a system of linear equations, <b>Ax = b</b>, with A QR factorized.
        /// </summary>
        /// <param name="input">The right hand side vector, <b>b</b>.</param>
        /// <returns>The left hand side <see cref="Vector{T}"/>, <b>x</b>.</returns>
        public Vector<T> Solve(Vector<T> input)
        {
            var x = Vector<T>.Builder.SameAs(this, ColumnCount);
            Solve(input, x);
            return x;
        }



        // Iterative Solvers: Full - 迭代求解


        // Iterative Solvers: Simple - 迭代求解







        // Factorizations - 因式分解

        public virtual Cholesky<T> Cholesky() => throw new Exception("overrid this function!");

        /// <summary>
        /// LU分解
        /// </summary>
        /// <returns></returns>
        public virtual LU<T> LU() => throw new Exception("overrid this function!");
        public virtual QR<T> QR(QRMethod method = QRMethod.Thin) => throw new Exception("overrid this function!");
        public virtual GramSchmidt<T> GramSchmidt() => throw new Exception("overrid this function!");
        public virtual Svd<T> Svd(bool computeVectors = true) => throw new Exception("overrid this function!");
        public virtual Evd<T> Evd(Symmetricity symmetricity = Symmetricity.Unknown) => throw new Exception("overrid this function!");


        //}}@@@
    }


}

